package com.liezh.allholloworld.itext7;

import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.geom.Vector;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.LocationTextExtractionStrategy;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liezh
 * @date 2022-1-13
 */
public class Itext7HelloWorld {
    public static final String DOG = "src/main/resources/img/sign.bmp";
    public static final String FOX = "src/main/resources/img/sign.bmp";

    public static final String DEST = "results/chapter01/quick_brown_fox.pdf";

    public static void main(String args[]) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(
                new PdfReader("src/main/resources/img/151271.pdf"),
                new PdfWriter("results/chapter01/151271.pdf"));
        final Itext7HelloWorld itext7HelloWorld = new Itext7HelloWorld();
        final List<List<float[]>> positions = itext7HelloWorld.findPdfTextEndPositions(pdfDoc, "患者家属签名");
        final ImageData imageData = ImageDataFactory.create(FOX);
        itext7HelloWorld.addImages(pdfDoc, positions, imageData);
        pdfDoc.close();
    }

    public void createPdf(String dest) throws IOException {
        //Initialize PDF writer
        PdfWriter writer = new PdfWriter(dest);

        //Initialize PDF document
        PdfDocument pdf = new PdfDocument(writer);

        // Initialize document
        Document document = new Document(pdf);

        // Compose Paragraph
        Image fox = new Image(ImageDataFactory.create(FOX));
        Image dog = new Image(ImageDataFactory.create(DOG));
        Paragraph p = new Paragraph("The quick brown ")
                .add(fox)
                .add(" jumps over the lazy ")
                .add(dog);
        // Add Paragraph to document
        document.add(p);

        //Close document
        document.close();
    }

    private void addImage(PdfDocument pdfDoc, int page, List<float[]> positions, ImageData imageData) throws IOException {
        final int numberOfPages = pdfDoc.getNumberOfPages();
        if (page > numberOfPages) {
            return;
        }
        final PdfPage pdfPage = pdfDoc.getPage(page);
        for (float[] pos : positions) {
            PdfCanvas canvas = new PdfCanvas(pdfPage.newContentStreamBefore(),
                    pdfPage.getResources(),
                    pdfDoc);
            canvas.saveState().addImageAt(imageData, pos[0], pos[1], true);
        }
    }

    private void addImages(PdfDocument pdfDoc, List<List<float[]>> pagePositions, ImageData imageData) throws IOException {
        for (int page = 1; page <= pagePositions.size(); ++page) {
            addImage(pdfDoc, page, pagePositions.get(page-1), imageData);
        }
    }

    /**
     * 获取对应文本结束位置坐标
     * https://kb.itextpdf.com/home/it7kb/faq/how-to-use-a-text-extraction-strategy-after-applying-a-location-extraction-strategy
     * @param document
     * @param query
     * @return
     */
    private List<List<float[]>> findPdfTextEndPositions(PdfDocument document, String query) {
        List<List<float[]>> positions = new ArrayList<>();
        for (int i = 1; i <= document.getNumberOfPages(); i++) {
            final PdfPage pdfPage = document.getPage(i);
            List<float[]> pagePositions = new ArrayList<>();
            LocationTextExtractionStrategy strategy =
                    new LocationTextExtractionStrategy((renderInfo, baseline) -> {
                        if (renderInfo.getText().contains(query)) {
                            System.out.println(renderInfo.getText());
                            final Vector endPoint = baseline.getEndPoint();
                            final float x = endPoint.get(0);
                            final float y = endPoint.get(1);
                            final float z = endPoint.get(2);
                            pagePositions.add(new float[]{x, y, z});
                        }
                        // 由于没有默认的策略，只能自己实现
                        return new MyITextChunkLocation(baseline.getStartPoint(), baseline.getEndPoint(), renderInfo.getSingleSpaceWidth());
                    });
            positions.add(pagePositions);
            PdfTextExtractor.getTextFromPage(pdfPage, strategy);
        }
        return positions;
    }
}
